from flask import abort
from flask import current_app, jsonify
from flask import g
from flask import redirect
from flask import render_template
from flask import request
from flask import session
from flask import url_for

from info import constants, db
from info.models import News, User, Comment, Category
from info.utils.common import login_data
from info.utils.image_storage import storage
from . import profile_blue
from info.utils.response_code import *


@profile_blue.route('/info')
@login_data
def info():
    user = g.user
    if not user:
        return redirect('/')

    data = {
        'user': user.to_dict()
    }
    return render_template('news/user.html', data=data)


# 基本资料路由
@profile_blue.route('/base_info', methods=['GET', 'POST'])
@login_data
def base_info():
    user = g.user
    if not user:
        return redirect('/')

    if request.method == 'GET':
        data = {
            'user': user.to_dict()
        }
        return render_template('news/user_base_info.html', data=data)

    else:
        # 表示是要提交表单中的数据到数据库
        params_dict = request.json
        nick_name = params_dict.get('nick_name')
        signature = params_dict.get('signature')
        gender = params_dict.get('gender')

        # 数据有效性和框定gender的范围
        if not all([nick_name, signature, gender]):
            return jsonify(errno=RET.PARAMERR, errmsg='参数缺少')
        if gender not in ['MAN', 'WOMAN']:
            return jsonify(errno=RET.PARAMERR, errmsg='性别有误')

        # 处理逻辑（把获取的数据更新到数据库）
        user.nick_name = nick_name
        user.signature = signature
        user.gender = gender

        try:
            db.session.commit()
        except Exception as e:
            db.session.rollback()
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='数据库更新错误')

        # 更新一下session中的nick_name
        session['nick_name'] = nick_name

        # 反回ok
        return jsonify(errno=RET.OK, errmsg='OK')


# 用户收藏
@profile_blue.route('/collection')
@login_data
def user_collection():
    user = g.user
    if not user:
        return redirect('/')

    # 获取参数当前页码(默认为1)
    page = request.args.get('page', 1)
    # 需要保证为int类型
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 查询数据库返回
    news_class_list = []
    total_page = 1
    current_page = 1
    try:
        paginate = user.collection_news.paginate(page, constants.USER_COLLECTION_MAX_NEWS, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

    news_class_list = paginate.items
    total_page = paginate.pages
    current_page = paginate.page

    news_list = []
    for news in news_class_list:
        news_list.append(news.to_review_dict())

    data = {
        'collections': news_list,
        'total_page': total_page,
        'current_page': current_page
    }
    return render_template('news/user_collection.html', data=data)


# 密码修改
@profile_blue.route('/pass_info', methods=['POST', 'GET'])
@login_data
def pass_info():
    user = g.user
    if not user:
        return jsonify(errno=RET.LOGINERR, errmsg='没有登录')

    # get请求
    if request.method == 'GET':
        return render_template('news/user_pass_info.html')

    # post请求
    # 1.获取参数
    params_dict = request.json
    old_password = params_dict.get('old_password')
    new_password = params_dict.get('new_password')

    # 2.数据有效性
    if not all([old_password, new_password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数缺失')

    # 3.逻辑处理（与数据库中的密码对比）
    if not user.check_passowrd(old_password):
        return jsonify(errno=RET.PWDERR, errmsg='原始密码错误')

    # 原密码正确可以修改
    user.password = new_password
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库修改出错')

    # 4.成功返回ok
    return jsonify(errno=RET.OK, errmsg='ok')


# 设置头像
@profile_blue.route('/pic_info', methods=['GET', 'POST'])
@login_data
def pic_info():
    user =g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='没有登录')
    if request.method == 'GET':
        data = {
            "user": user.to_dict()
        }
        return render_template('news/user_pic_info.html', data=data)

    # 提交图片到七牛云并传递地址到前端
    # 1.获取参数(图片所在的路径)
    try:
        avatar = request.files.get('avatar').read()
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='文件读取失败')

    # 2.调用七牛云封装的图像上传工具
    try:
        avatar_url = storage(avatar)
    except Exception as e:
        return jsonify(errno=RET.THIRDERR, errmsg='上传图片失败')
    # 3.保存url地址到数据库
    user.avatar_url = avatar_url
    try:
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库存储失败')

    # 返回ok
    return jsonify(errno=RET.OK, errmsg='ok', data={"avatar_url": constants.QINIU_DOMIN_PREFIX + avatar_url})


# 新闻发布
@profile_blue.route('/news_release', methods=['GET', 'POST'])
@login_data
def news_release():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='没有登录')

    if request.method == 'GET':

        # 查询所有的新闻分类
        try:
            categories = Category.query.all()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='查询数据库错误')

        category_list = []
        for category in categories:
            category_list.append(category.to_dict())

        category_list.pop(0)

        data = {
            'category_list': category_list
        }

        return render_template('news/user_news_release.html', data=data)

    # POST请求，要发布新闻
    # 1.获取参数（标题，分类，摘要，图片地址，内容）
    title = request.form.get('title')
    category_id = request.form.get('category_id')
    digest = request.form.get('digest')
    content = request.form.get('content')

    try:
        index_image = request.files.get('index_image').read()
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='读取图像失败')

    try:
        index_image_url = storage(index_image)
    except Exception as e:
        return jsonify(errno=RET.THIRDERR, errmsg='七牛云存储文件失败')

    # 2.校验参数（数据有效性，title不超过20个字，分类传过来的id是int类型）
    if not all([title, category_id, digest, index_image, content]):
        return jsonify(errno=RET.PARAMERR, errmsg='缺少参数')
    if len(title) > 20:
        return jsonify(errno=RET.PARAMERR, errmsg='标题不超过20个字')
    try:
        category_id = int(category_id)
    except Exception as e:
        return jsonify(errno=RET.PARAMERR, errmsg='参数错误')

    # 3.处理逻辑（存储到数据库）
    news = News()
    news.title = title
    news.category_id = category_id
    news.digest = digest
    news.content = content
    news.user_id = user.id
    news.source = '个人发布'
    news.status = 1
    news.index_image_url = constants.QINIU_DOMIN_PREFIX + index_image_url

    try:
        db.session.add(news)
        db.session.commit()
    except Exception as e:
        db.session.rollback()
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库存储错误')

    return jsonify(errno=RET.OK, errmsg='ok')


# 个人中心新闻列表
@profile_blue.route('/news_list')
@login_data
def news_list():
    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='没登录')

    # 获取分页参数（有默认值）
    page = request.args.get('page', 1)  # 当前页
    # 确保是int类型
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    # 显示的是查询的我发布的新闻
    try:
        paginate = News.query.filter(News.user_id == user.id).paginate(page, constants.OTHER_NEWS_PAGE_MAX_COUNT, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

    news_class_list = paginate.items
    current_page = paginate.page
    total_pages = paginate.pages

    news_list = []
    for news in news_class_list:
        news_list.append(news.to_review_dict())

    data = {
        "news_list": news_list,
        "current_page": current_page,
        "total_pages": total_pages,
    }
    return render_template('news/user_news_list.html', data=data)


# 个人中心关注列表
@profile_blue.route('/user_follow')
@login_data
def user_follow():

    user = g.user
    if not user:
        return jsonify(errno=RET.SESSIONERR, errmsg='没有登录')

    # 获取参数
    page = request.args.get('page', 1)
    # 数据是否是int
    try:
        page = int(page)
    except Exception as e:
        current_app.logger.error(e)
        page = 1

    try:
        paginate = user.followed.paginate(page, constants.USER_FOLLOWED_MAX_COUNT, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

    author_class_list = paginate.items
    current_page = paginate.page
    total_pages = paginate.pages

    author_list = []
    for author in author_class_list:
        author_list.append(author.to_dict())

    data = {
        'author_list': author_list,
        'current_page': current_page,
        'total_pages': total_pages
    }

    return render_template('news/user_follow.html', data=data)


# 其他用户页面
@profile_blue.route('/others')
@login_data
def others():
    user = g.user
    if not user:
        return redirect(url_for('index.index'))

    # 获取参数（作者id, 新闻列表当前页）
    author_id = request.args.get('author_id')
    page = request.args.get('page', 1)

    try:
        page = int(page)
    except Exception as e:
        page = 1

    try:
        author_id = int(author_id)
    except Exception as e:
        return jsonify(errorno=RET.PARAMERR, errmsg='参数格式错误或缺少')

    # 获取了作者id，查询数据库中的该作者信息
    try:
        author = User.query.get(author_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')

    if not author:
        return jsonify(errno=RET.NODATA, errmsg='没有该用户')

    is_followed = False
    if user in author.followers:
        is_followed = True

    # 作者发布的新闻列表
    try:
        paginate = author.news_list.paginate(page, constants.OTHER_NEWS_PAGE_MAX_COUNT, False)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据库查询错误')
    news_class_list = paginate.items
    current_page = paginate.page
    total_pages = paginate.pages

    news_list =[]
    for news in news_class_list:
        news_list.append(news.to_review_dict())

    data = {
        'user': user.to_dict(),
        'author': author.to_dict(),
        'is_followed': is_followed,
        'news_list': news_list,
        'current_page': current_page,
        'total_pages': total_pages,
    }
    return render_template('news/other.html', data=data)